/*
Kakine
ActionScript Framework
Copyright © 2011, PUNY, LLC.

This file is part of KAKINE.

KAKINE is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

KAKINE is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with KAKINE.  If not, see <http://www.gnu.org/licenses/>.
*/ 
package com.puny.mvc.controllers.platformer
{
	import com.puny.mvc.BaseObject;
	import com.puny.mvc.MvcEvent;
	import com.puny.mvc.views.platformer.ItemView;
	import com.puny.xmlutils.XMLReader;
	
	import flash.events.Event;
	import flash.geom.Point;
	/**
	 * $Revision: 706 $<br/>
	 * Stage controller for a platformer game.
	 * 
	 */
	public class PlatformerStageController extends EasingController
	{
		private var _mainCharacter:IMainCharacterController;
		private var _gravity:Point;
		private var _threshold:Number;
		private var _items:Array = new Array();
		private var _laters:Array = new Array();
		private var _characters:Array = new Array();
		private var _buff_chars:Array = new Array();
//		private var _materials:Array = new Array();
//		private var _buff_mats:Array = new Array();
		private var _medkits:Array = new Array();
		public function PlatformerStageController(filename:String,mainCharacter:IMainCharacterController)
		{
			_mainCharacter = mainCharacter;
			super(filename);
		}
		
		protected function set threshold(value:Number):void {
			_threshold = value;
		}
		
		protected function setupDeck(list:XMLList, cls:Class, arr:Array,src:String,buff:Array,comp:Boolean=true):void {
			var base:BaseObject;
			for each(var enemy:XML in list) {
//				trace(">"+enemy.attribute("src").length()+"<");
				if (!enemy.hasOwnProperty("@url")) {
					enemy.@url = src;
				}
				base = new cls(enemy);
				addChild(base);
				if (arr!=null) {
					if (XMLReader.attributeBoolean(enemy,"later")) {
						_laters.push(base);
					} else if (buff!=null && enemy.@x > _threshold) {
						buff.push(base);
					} else {
						arr.push(base);
					}
				}
				if (comp) {
					base.addEventListener(MvcEvent.COMPLETED, completedHandler);
				}
			}
		}
		
		override protected function setup():void {
			if (mainCharacter != null) {
				addChild(mainCharacter as CharacterController);
				_characters.push(mainCharacter);
//				setupMainCharacter();
			}
		}
		
		
		protected function set gravity(value:Point):void {
			_gravity = value;
		}
						
		protected function get gravity():Point {
			return _gravity;
		}
		
		protected function get items():Array {
			return _items;
		}
		
		protected function get characters():Array {
			return _characters;
		}
		
		protected function get characters_buffer():Array {
			return _buff_chars;
		}
		
		protected function get medKits():Array {
			return _medkits;
		}
		
//		protected function get materials():Array {
//			return _materials;
//		}
//
//		protected function get materials_buffer():Array {
//			return _buff_mats;
//		}
		
		protected function get laters():Array {
			return _laters;
		}
		
		override public function beforeReady():void {
			super.beforeReady();
			if (_mainCharacter != null) {
				(_mainCharacter as CharacterController).addEventListener(VerletController.MOVING, slidingHandler);
				slidingHandler();
			}
		}
		
		public function get mainCharacter():IMainCharacterController {
			return _mainCharacter;
		}
		
		private function slidingHandler(event:Event=null):void {
			if (_mainCharacter != null) {
				var dx:Number = (_mainCharacter.screenX-(_mainCharacter as CharacterController).x) - x;
				var dy:Number = (_mainCharacter.screenY-(_mainCharacter as CharacterController).y) - y;
				if ((_mainCharacter as CharacterController).x > _threshold - 800) {
					while(_buff_chars.length != 0) {
						characters.unshift(_buff_chars.pop());
					}
//					while(_buff_mats.length != 0) {
//						materials.unshift(_buff_mats.pop());
//					}
				}
				slideTo(dx, dy);
			}
		}	
		
		override public function procedureMainFrame():Boolean {
			for each(var character:CharacterController in _characters) {
				character.move(_gravity);
				collision(character);
//				collision3(character);
			}
//			for each(var material:CharacterController in _materials) {
//				material.move(_gravity);
//				collision(material);
//			}
			collision2(_mainCharacter as CharacterController);
			return true;
		}
		
		protected function collision2(character:CharacterController):void {
			if (character !=null) {
				var kit:ItemView
				var length:int = _medkits.length;
				for(var i:int = 0;i < length;i++) {
					kit = _medkits[i];
					if (character.hitTestObject(kit)) {
						(character as IMainCharacterController).recover(kit);
						kit.complete();
						_medkits.splice(i,1);
						i--;
						length--;
					}
				}
			}
		}

//		protected function collision3(character:CharacterController):void {
//			var target:CharacterController = null;
//			var length:int = _materials.length;
//			var index:int;
//
//			//Characters v.s. Materials
//			for (index = 0;index < length;index++) {
//				target = _materials[index];
//				if (target != character && character.hitTestObject(target)) {
//					if (character.hit(target)) {
//						_materials.splice(index,1);
//						index--;
//						length--;
//					}
//					//trace(character, "hits", target);
//				}
//			}
//			
//		}		

		protected function collision(character:CharacterController):void {
			
			//Characters v.s. Characters.
			var target:CharacterController = null;
			var length:int = _characters.length;
			var index:int;
			for (index = 0;index < length;index++) {
				target = _characters[index];
				if (target != character && character.hitTestObject(target)) {
					if (character.hit(target)) {
						_characters.splice(index,1);
						index--;
						length--;
					}
					//trace(character, "hits", target);
				}
			}
			

			//Characters v.s. Items.
			for each(var item:ItemView in _items) {
				if (character.hitTestObject(item)) {
					character.adjustMovement(_gravity,item);
				}
			}
			
		}
		
		private function completedHandler(event:Event):void {
			var index:int = _characters.indexOf(event.currentTarget);
			if (index >= 0) {
				_characters.splice(index,1);
//			} else {
//				index = _materials.indexOf(event.currentTarget);
//				if (index >= 0) {
//					_materials.splice(index,1);
//				}
			}
		}
		
		override public function beforeClose():void {
			super.beforeClose();
			while(_items.length>0) {
				_items.pop();
			}
			while(_characters.length>0) {
				_characters.pop();				
			}
//			while(_materials.length>0) {
//				_materials.pop();
//			}
			while(_laters.length>0) {
				_laters.pop();
			}
		}
		
		override public function afterClose():void {
			_mainCharacter = null;
		}
	}
}